#include "TabBar.h"

#include <core/Events.h>
#include <core/ImageMgr.h>
#include <core/StyleMgr.h>
#include <widgets/SImageButton.h>

#include <QAction>
#include <QApplication>
#include <QDrag>
#include <QHBoxLayout>
#include <QLinearGradient>
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
#include <QPropertyAnimation>
#include <QScreen>
#include <QToolTip>

#include "../CMD/CmdMgr.h"
#include "../ModuleMgr.h"

namespace {
class SMenuItem : public QWidget {
 public:
  SMenuItem(QWidget* parent = nullptr)
      : QWidget(parent), m_text(""), m_checked(false) {}
  ~SMenuItem() {}
  void setText(const QString& txt) { m_text = txt; }
  void setCheck(bool checked) {
    m_checked = checked;
    update();
  }

 protected:
  virtual void paintEvent(QPaintEvent* event) override {
    QMargins margins = contentsMargins();
    QRect rect = contentsRect();
  }

 private:
  QString m_text;
  bool m_checked;
};
}  // namespace

static bool s_disable_layout = true;
TabBar::TabBar(QWidget* parent) : QWidget(parent) {
  setAcceptDrops(true);
  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  setFixedHeight(m_layout.tab_image_height);

  m_pmDragCursor = QPixmap(":/guiframe/image/aero_arrow/aero_arrow_normal.png");
  m_pmDragCursor = m_pmDragCursor.scaled(16, 25, Qt::KeepAspectRatio,
                                         Qt::SmoothTransformation);

#pragma region Test Code
/*
        for (int i = 0; i < 2; ++i)
                addTab(QString::number(i), 0, 0, true);

        for (int i = 2; i < 10; ++i)
                addTab("标签页: " + QString::number(i), 0, 0, false);
                */
#pragma endregion

  QHBoxLayout* layout = new QHBoxLayout();
  layout->setContentsMargins(0, 0, 0, 3);
  layout->setSpacing(0);

  m_btnMore = new SImageButton(this, "guiframe_action_more");
  m_btnMore->setToolTip("更多操作");
  m_btnMore->setFixedSize(24, 24);
  m_btnMore->setColor(NAME_COLOR("ElementBackground"), NAME_COLOR("Hover"),
                      NAME_COLOR("Hover"), NAME_COLOR("ElementBackground"));

  // m_btnMore->setStyleSheet("QToolTip{border:1px solid #308376;font:12px
  // Microsoft
  // YaHei;font-weight:bold;background-color:rgb(9,36,36);color:rgb(255, 235,
  // 200)}");
  m_btnRefresh = new SImageButton(this, "guiframe_action_refresh");
  m_btnRefresh->setToolTip("刷新");
  m_btnRefresh->setFixedSize(24, 24);
  m_btnRefresh->setColor(NAME_COLOR("ElementBackground"), NAME_COLOR("Hover"),
                         NAME_COLOR("Hover"), NAME_COLOR("ElementBackground"));
  // m_btnRefresh->setStyleSheet("QToolTip{border:1px solid #308376;font:12px
  // Microsoft
  // YaHei;font-weight:bold;background-color:rgb(9,36,36);color:rgb(255, 235,
  // 200)}");
  m_btnRefresh->setDisabled(true);

  layout->addStretch();
  layout->addWidget(m_btnMore, 0, Qt::AlignBottom);
  layout->addWidget(m_btnRefresh, 0, Qt::AlignBottom);
  setLayout(layout);

  m_activePos = 0;
  setMouseTracking(true);
  s_disable_layout = false;

  m_animation = new QPropertyAnimation(this, "animateProgess");
  m_animation->setStartValue(0);
  m_animation->setEndValue(100);
  m_animation->setDuration(200);

  buildActions();
}

void TabBar::layoutTabs(bool reset) {
  if (s_disable_layout || m_tabs.isEmpty()) return;

  QRect r = rect();
  // 新增tab时，永远加在第一个，需重置隐藏tab
  if (reset) {
    for (int pos : m_hideTabs) {
      m_tabs[pos].setHide(false);
    }
    m_hideTabs.clear();
    m_layout.showMore = false;
  }

  if (m_layout.showMore) {
    int rightBtnWidth = m_layout.right_btn_width * 3;
    int curTabsWidth = 0;
    for (auto tab : m_tabs) {
      if (!tab.isHide()) curTabsWidth += tab.rect.width();
    }
    int leftSpace = rect().width() - rightBtnWidth - curTabsWidth;

    // check right
    for (auto iter = m_hideTabs.begin(); iter != m_hideTabs.end(); ++iter) {
      if (*iter < m_activePos) continue;

      leftSpace -= m_layout.fixedWidth ? m_layout.normal_tab_width
                                       : m_layout.min_tab_width;
      if (leftSpace >= 0) {
        m_tabs[*iter].setHide(false);
      } else
        break;
    }

    // check left
    for (auto iter = m_hideTabs.rbegin(); iter != m_hideTabs.rend(); ++iter) {
      if (*iter > m_activePos) continue;

      leftSpace -= m_layout.fixedWidth ? m_layout.normal_tab_width
                                       : m_layout.min_tab_width;
      if (leftSpace >= 0) {
        m_tabs[*iter].setHide(false);
      } else
        break;
    }

    for (auto iter = m_hideTabs.begin(); iter != m_hideTabs.end();) {
      if (!m_tabs[*iter].isHide())
        iter = m_hideTabs.erase(iter);
      else
        ++iter;
    }
    if (m_hideTabs.isEmpty()) m_layout.showMore = false;
  }

  // 未有隐藏tab时，根据tab数目计算tab宽度
  if (!m_layout.showMore) {
    int rightBtnWidth = m_layout.right_btn_width * 2;
    int availableWidth = r.width() - rightBtnWidth;  // more & refresh showmore
    int tabsCount = m_tabs.size();
    if (tabsCount > m_fixedCount) {
      availableWidth -= m_layout.group_gap;
      availableWidth += (tabsCount - m_fixedCount - 1) * m_layout.tab_overlap;
    }

    // 考虑tab重叠
    availableWidth += (m_fixedCount - 1) * m_layout.tab_overlap;

    // 激活状态的tab宽度固定
    if (!m_layout.fixedWidth) {
      int tabWidth =
          tabsCount > 1
              ? (availableWidth - m_layout.active_tab_width) / (tabsCount - 1)
              : m_layout.max_tab_width;
      // tabWidth = std::min(tabWidth, m_layout.max_tab_width);
      tabWidth =
          tabWidth > m_layout.max_tab_width ? m_layout.max_tab_width : tabWidth;
      if (tabWidth <= m_layout.min_tab_width) {
        tabWidth = m_layout.min_tab_width;
        m_layout.showMore = true;
      }
      m_layout.normal_tab_width = tabWidth;
    } else {
      if (tabsCount > 1 &&
          m_layout.active_tab_width * (tabsCount - 1) > availableWidth)
        m_layout.showMore = true;
    }
  }

  // 计算rect
  m_tabsForAnimate = m_tabs;
  int availableWidth =
      r.width() - (m_layout.right_btn_width * (m_layout.showMore ? 3 : 2));
  QRect tabR(0, 0, m_layout.normal_tab_width, m_layout.tab_image_height);
  for (int i = 0; i < m_tabs.size(); ++i) {
    if (m_hideTabs.contains(i)) continue;

    if (i == m_activePos)
      tabR.setWidth(m_layout.active_tab_width);
    else
      tabR.setWidth(m_layout.normal_tab_width);
    m_tabs[i].rect = tabR;

    // 固定标签不能隐藏
    if (i >= m_fixedCount && tabR.right() > availableWidth) {
      if (!m_hideTabs.contains(i)) m_hideTabs.push_back(i);
      m_tabs[i].setHide(true);
      std::sort(m_hideTabs.begin(), m_hideTabs.end());
    }

    if (i == m_fixedCount - 1)
      tabR.moveLeft(tabR.right() + m_layout.group_gap);
    else
      tabR.moveLeft(tabR.right() - m_layout.tab_overlap);
  }

  if (m_fixedCount > 0) {
    int x = m_tabs[m_fixedCount - 1].rect.right() - 2;
    m_rectMoveLeft.setRect(x, 12, 14, 14);
    x = m_btnMore->geometry().left() - 4 - 14;
    m_rectMoveRight.setRect(x, 12, 14, 14);
  }

  update();
}

CmdWindowInfo& TabBar::addTab(const QString& title, QWidget* ctrl, int cmdId,
                              bool fixed) {
  CmdWindowInfo ti;
  ti.title = title;
  ti.cmdId = cmdId;
  ti.widget = ctrl;
  ti.winId = CmdMgr::instance().cmdWindowId();
  if (fixed) ti.setFixed(true);

  int index = m_fixedCount;
  m_tabs.insert(index, ti);

  if (!fixed && m_activePos >= m_fixedCount) ++m_activePos;

  if (fixed) ++m_fixedCount;

  // 调整隐藏tab的索引
  for (int& pos : m_hideTabs) {
    ++pos;
  }

  int oldTabWidth = m_layout.normal_tab_width;
  activateWindow(index);

  int requestReiszeType = -1;
  if (oldTabWidth == m_layout.max_tab_width &&
      m_layout.normal_tab_width < m_layout.max_tab_width)
    requestReiszeType = 0;

  if (requestReiszeType != -1) requestResize(requestReiszeType);
  return m_tabs[index];
}

CmdWindowInfo* TabBar::tabById(int tabId) {
  for (int i = 0; i < m_tabs.size(); ++i) {
    if (m_tabs[i].winId == tabId) return &(m_tabs[i]);
  }

  return nullptr;
}

int TabBar::tabForCmd(int id, const QString& params) {
  for (const CmdWindowInfo& ti : m_tabs) {
    if (ti.cmdId == id &&
        ti.params.compare(params, Qt::CaseSensitivity::CaseInsensitive) == 0)
      return ti.winId;
  }
  return -1;
}

void TabBar::closeTab(int pos) {
  if (pos < m_fixedCount) return;

  if (!m_dragging) {
    tabClose(m_tabs[pos].winId);
  }

  m_hideTabs.removeOne(pos);
  for (int& tabPos : m_hideTabs) {
    if (tabPos > pos) --tabPos;
  }

  CmdWindowInfo ti = m_tabs[pos];
  m_activeHistory.removeAll(m_tabs[pos].winId);
  m_tabs.erase(m_tabs.begin() + pos);

  // switch active tab
  if (m_activePos == pos) {
    if (m_activeHistory.isEmpty())
      m_activePos = 0;
    else {
      m_activePos = tabPosById(m_activeHistory.top());
    }
  } else if (m_activePos > pos)
    --m_activePos;

  // if (m_activePos == pos)
  //	return;

  // TODO:使之前激活的tab显示出来
  if (m_activePos < 0 || m_tabs[m_activePos].isHide()) m_activePos = 0;

  int oldTabWidth = m_layout.normal_tab_width;

  layoutTabs();
  startAnimation();
  tabActivated(m_tabs[m_activePos].winId);

  // TODO:need more accurate
  if (m_layout.normal_tab_width == m_layout.max_tab_width) requestResize(1);
}

void TabBar::insertTab(const CmdWindowInfo& ti, int pos) {
  m_tabs.insert(pos, ti);
  for (int& tabPos : m_hideTabs) {
    if (tabPos > pos) ++tabPos;
  }
  int oldTabWidth = m_layout.normal_tab_width;
  layoutTabs();

  int requestReiszeType = -1;
  if (oldTabWidth == m_layout.max_tab_width &&
      m_layout.normal_tab_width < m_layout.max_tab_width)
    requestReiszeType = 0;

  if (requestReiszeType != -1) requestResize(requestReiszeType);
}

// TODO: show the hide one
void TabBar::activateWindow(int index) {
  if (index >= 0 && index < m_tabs.size() && m_activePos != index) {
    // if the tab is hidden, show it
    if (m_hideTabs.contains(index)) {
      // if the tab is in left, hide right tabs firstly
      bool isInLeft = false;
      bool firstVisibleFound = false;
      for (int i = index + 1; i < m_tabs.size(); ++i) {
        if (!m_tabs[i].isHide()) {
          if (!firstVisibleFound)
            firstVisibleFound = true;
          else {
            isInLeft = true;
            break;
          }
        }
      }

      m_tabs[index].setHide(false);
      m_hideTabs.removeOne(index);
      int hideIndex = -1;
      if (isInLeft) {
        for (int i = m_tabs.size() - 1; i >= m_fixedCount; --i) {
          if (!m_tabs[i].isHide()) {
            hideIndex = i;
            break;
          }
        }
      } else {
        for (int i = m_fixedCount; i < m_tabs.size(); ++i) {
          if (!m_tabs[i].isHide()) {
            hideIndex = i;
            break;
          }
        }
      }
      if (hideIndex != -1) {
        m_tabs[hideIndex].setHide(true);
        m_hideTabs.push_back(hideIndex);
        std::sort(m_hideTabs.begin(), m_hideTabs.end());
      }
    }

    m_activePos = index;
    stopAnimation();

    layoutTabs();
    m_activeHistory.push(m_tabs[index].winId);
    startAnimation();
    tabActivated(m_tabs[m_activePos].winId);
  }
}

void TabBar::onMoveBtnClicked(bool left) {
  if (left && checkLeftHide()) {
    bool hide = false;
    for (int i = m_tabs.size() - 1; i >= m_fixedCount; --i) {
      // hide last none active tab
      if (!hide && i != m_activePos && !m_tabs[i].isHide()) {
        m_tabs[i].setHide(true);
        m_hideTabs.push_back(i);
        std::sort(m_hideTabs.begin(), m_hideTabs.end());
        hide = true;
        continue;
      }

      if (hide && m_tabs[i].isHide()) {
        m_tabs[i].setHide(false);
        m_hideTabs.erase(m_hideTabs.begin() + m_hideTabs.indexOf(i));
        std::sort(m_hideTabs.begin(), m_hideTabs.end());
        break;
      }
    }

    layoutTabs();
  }

  if (!left && checkRightHide()) {
    bool hide = false;
    for (int i = m_fixedCount; i < m_tabs.size(); ++i) {
      // hide first none active tab
      if (!hide && i != m_activePos && !m_tabs[i].isHide()) {
        m_tabs[i].setHide(true);
        m_hideTabs.push_back(i);
        std::sort(m_hideTabs.begin(), m_hideTabs.end());
        hide = true;
        continue;
      }
      if (hide && m_tabs[i].isHide()) {
        m_tabs[i].setHide(false);
        m_hideTabs.erase(m_hideTabs.begin() + m_hideTabs.indexOf(i));
        break;
      }
    }
    layoutTabs();
  }
}

bool TabBar::checkLeftHide() const {
  if (m_hideTabs.isEmpty()) return false;

  if (m_hideTabs.first() == m_fixedCount ||
      m_hideTabs.first() == m_fixedCount + 1)
    return true;

  return false;
}

bool TabBar::checkRightHide() const {
  if (m_hideTabs.isEmpty()) return false;

  if (m_hideTabs.last() == m_tabs.size() - 1 ||
      m_hideTabs.last() == m_tabs.size() - 2)
    return true;

  return false;
}

QPixmap TabBar::getDragPixmap() const {
  if (m_dragTab.widget) {
    QScreen* screen = QGuiApplication::primaryScreen();
    QPixmap pm = screen->grabWindow(m_dragTab.widget->winId());
    pm = pm.scaledToWidth(150);
    QPixmap newPm(pm.width() + 2, pm.height() + 2);
    newPm.fill(Qt::transparent);
    QPainter painter(&newPm);
    painter.drawPixmap(1, 1, pm.width(), pm.height(), pm);
    QRect border;
    border.setRect(0, 0, pm.width() + 1, pm.height() + 1);
    painter.setPen(Qt::darkGray);
    painter.drawRect(border);
    return newPm;
  }
  return QPixmap::fromImage(
      *(ImgMgr::instance()
            .image("guiframe_app_logo_title", WidgetStatus::kNormal, 2)
            ->img()));
}

void TabBar::activateTabByTabId(int tabId) {
  for (int i = 0; i < m_tabs.size(); ++i) {
    if (m_tabs[i].winId == tabId) {
      activateWindow(i);
      break;
    }
  }
}

void TabBar::updateTabTitle(int tabId, const QString& title) {
  for (int i = 0; i < m_tabs.size(); ++i) {
    if (m_tabs[i].winId == tabId) {
      m_tabs[i].title = title;
      break;
    }
  }
  update();
}

void TabBar::attachWidget(CmdWindowInfo cwi) {
  if (cwi.widget == nullptr) return;

  m_dragTab = cwi;
  startDrag();
}

bool TabBar::event(QEvent* event) {
  if (event->type() == QEvent::ToolTip) {
    QHelpEvent* he = static_cast<QHelpEvent*>(event);
    int tabIndex = hitTestTab(he->pos());
    if (tabIndex != -1) {
      const CmdWindowInfo& ti = m_tabs[tabIndex];
      QRect txtRect = fontMetrics().boundingRect(ti.title);
      if (txtRect.width() > ti.rect.width() - 6 * 2) {
        QToolTip::showText(he->globalPos(), ti.title);
        return true;
      }
    }

    QToolTip::hideText();
    he->ignore();
    return true;
  } else if (event->type() == (QEvent::Type)SSEventType::UserScaleChanged) {
    float scale = getAppInstance()->uiScale();
    m_layout.applyScale(scale);
    setFixedHeight(m_layout.tab_image_height + 1);

    layout()->setContentsMargins(0, 0, 0, 3 * scale);
    resize(width(), m_layout.tab_image_height + 1);
    layoutTabs(true);
  }

  return QWidget::event(event);
}

void TabBar::mousePressEvent(QMouseEvent* e) {
  m_startDragPos = e->globalPos();
  int tabIndex = hitTestTab(e->pos());
  if (tabIndex == -1) {
    if (!m_layout.showMore) return;

    if (m_rectMoveLeft.contains(e->pos()))
      onMoveBtnClicked(true);
    else if (m_rectMoveRight.contains(e->pos()))
      onMoveBtnClicked(false);

    return;
  }
}

void TabBar::mouseDoubleClickEvent(QMouseEvent* e) {
  int tabIndex = hitTestTab(e->pos());
  if (tabIndex != -1) {
    closeTab(tabIndex);
  }
}

void TabBar::mouseReleaseEvent(QMouseEvent* e) {
  if (e->button() != Qt::LeftButton) return;

  int tabIndex = hitTestTab(e->pos());
  if (tabIndex == -1) return;

  int clickIndex =
      hitTestTab(mapFromGlobal(m_startDragPos));  // 鼠标点击和释放的位置不同
  if (clickIndex != tabIndex) return;

  if (!m_tabs[tabIndex].isFixed()) {
    QRect r = m_tabs[tabIndex].rect;
    QRect closeR(
        QPoint(r.right() - m_layout.clost_btn_gap - m_layout.close_btn_width,
               r.bottom() - m_layout.clost_btn_gap - m_layout.close_btn_width),
        QSize(m_layout.close_btn_width, m_layout.close_btn_width));
    bool clickOnClose = closeR.contains(e->pos());
    if (clickOnClose) {
      closeTab(tabIndex);
      return;
    }
  }

  activateWindow(tabIndex);
}

void TabBar::resizeEvent(QResizeEvent* event) {
  stopAnimation();
  layoutTabs();
  startAnimation();
}

void TabBar::leaveEvent(QEvent* event) {
  m_hoverPos = -1;
  // if move too quickly, dragLeaveEvent will not be received!
  if (m_dragging && !rect().contains(mapFromGlobal(QCursor::pos())))
    closeTab(tabPosById(m_dragTab.winId));
  update();
}

void TabBar::dragEnterEvent(QDragEnterEvent* event) {
  if (event->mimeData()->hasFormat("application/x-dnditemdata") &&
      event->source() == this)
    event->acceptProposedAction();
  else
    event->ignore();
}

void TabBar::dragLeaveEvent(QDragLeaveEvent* event) {
  closeTab(tabPosById(m_dragTab.winId));
}

void TabBar::dragMoveEvent(QDragMoveEvent* e) {
  int tabPosX = (e->pos() + m_dragOffset).x();
  doDragMove(tabPosX);
}

void TabBar::dropEvent(QDropEvent* event) {
  if (event->mimeData()->hasFormat("application/x-dnditemdata") &&
      event->source() == this)
    event->acceptProposedAction();
}

void TabBar::mouseMoveEvent(QMouseEvent* e) {
  if ((e->buttons().testFlag(Qt::LeftButton)) &&
      (e->globalPos() - m_startDragPos).manhattanLength() >=
          QApplication::startDragDistance()) {
    int clickIndex = hitTestTab(
        mapFromGlobal(m_startDragPos));  // 检查是否是从首页标签开始drag
    int tabIndex = hitTestTab(e->pos());
    if (tabIndex > 0 && clickIndex > 0)  // 首页不能动
    {
      m_activePos = tabIndex;
      layoutTabs();
      m_dragTab = m_tabs[tabIndex];
      m_dragOffset = m_dragTab.rect.topLeft() - e->pos();

      startDrag();
    }
  }

  int tabPos = hitTestTab(e->pos());
  bool needUpdate = tabPos != m_hoverPos;
  m_hoverPos = tabPos;

  if (needUpdate) update();
}

void TabBar::contextMenuEvent(QContextMenuEvent* event) {
  int tabIndex = hitTestTab(event->pos());
  if (tabIndex <= 0) return;

  m_tabMenu = tabIndex;
  QMenu ctxMenu(this);
  ctxMenu.addAction(m_actionRefresh);
  ctxMenu.addAction(m_actionFix);
  ctxMenu.addAction(m_actionClose);
  ctxMenu.addAction(m_actionCloseOthers);
  ctxMenu.addAction(m_actionCloseAll);
  ctxMenu.addAction(m_actionCloseAllBonds);

  const CmdWindowInfo& ti = m_tabs[tabIndex];
  m_actionRefresh->setEnabled(ti.isWeb());

  if (ti.isFixed()) {
    m_actionFix->setText(tr("取消固定页面"));
    m_actionClose->setEnabled(false);
  } else {
    m_actionFix->setText(tr("固定页面"));
    m_actionClose->setEnabled(true);
  }

  m_actionCloseOthers->setEnabled(m_tabs.size() > m_fixedCount);
  m_actionCloseAll->setEnabled(m_tabs.size() > m_fixedCount);

  ctxMenu.setStyleSheet(
      QString("QMenu::item {padding:6px 38px 6px 18px}\n"
              "QMenu::item:hover {background-color:#%1}\n"
              "QMenu::item:disabled {color:#%2}\n"
              "QMenu {background-color:#%3; margin:0px;font:12px Microsoft "
              "YaHei;font-weight:bold;}")
          .arg(NAME_COLOR("Hover").rgb(), 0, 16)
          .arg(NAME_COLOR("SupportingWord").rgb(), 0, 16)
          .arg(NAME_COLOR("ElementBackground").rgb(), 0, 16));

  ctxMenu.exec(event->globalPos());
}

int TabBar::leftSpace() const {
  return rect().width() - m_tabs.last().rect.right() -
         m_layout.right_btn_width * 2;
}

void TabBar::paintEvent(QPaintEvent* event) {
  QVector<CmdWindowInfo> tis = m_tabs;
  if (m_animating) tis = m_tabsForAnimate;

  if (tis.isEmpty()) return;

  QStylePainter painter(this);
  painter.setRenderHint(QPainter::Antialiasing);
  painter.setRenderHint(QPainter::SmoothPixmapTransform);
  painter.fillRect(rect(), NAME_COLOR("ElementBackground"));

  for (int i = 0; i < tis.size(); ++i) {
    // if (i == m_activePos)
    //	continue;
    drawTab(painter, tis[i], false, m_hoverPos == i);
  }

  if (m_activePos >= 0 && m_activePos < tis.size())
    drawTab(painter, tis[m_activePos], true, m_hoverPos == m_activePos);

  drawMoveBtns(painter);
}

void TabBar::drawTab(QStylePainter& painter, const CmdWindowInfo& ti,
                     bool isActive, bool isHover) {
  if (ti.isHide()) return;

  bool isDraggingTab = m_dragging && ti.winId == m_dragTab.winId;
  if (isDraggingTab) {
    painter.save();
    painter.setOpacity(0.8);
  }

  QRect tabRect = ti.rect;
  tabRect.adjust(0, 2, 0, -2);
  int imgGap = m_layout.image_gag;
  if (isActive) {
    if (m_dragging && isDraggingTab) {
      QPoint pos = mapFromGlobal(QCursor::pos()) + m_dragOffset;
      pos.setY(0);
      tabRect.moveTo(pos);
    }

    /*SImage* img = ImgMgr::instance().image("guiframe_app_label_selected",
    WidgetStatus::kNormal, devicePixelRatioF()); if (img)
    {
            QRect imgR = img->rect();
            imgR.adjust(imgGap, 0, -imgGap, 0);
            painter.drawImage(tabRect, *img, imgR);
    }
    else
    {

    }*/

    QLinearGradient lg(ti.rect.right(), ti.rect.top(), ti.rect.right(),
                       ti.rect.bottom());
    lg.setColorAt(0, QColor(255, 170, 76));
    lg.setColorAt(1, QColor(255, 108, 0));
    painter.setPen(Qt::NoPen);
    painter.setBrush(QBrush(lg));
    painter.drawRoundedRect(tabRect, 2, 2);

    //	QLinearGradient lg(ti.rect.left(), ti.rect.bottom(), ti.rect.right(),
    //ti.rect.bottom()); 	lg.setColorAt(0, NAME_COLOR("HighLightArea_L1"));
    //	lg.setColorAt(1, NAME_COLOR("HighLightArea_L2"));
    //	QPen pen;
    //	pen.setWidth(2);
    //	pen.setBrush(lg);
    //	painter.setPen(pen);
    //	painter.drawLine(QPoint(ti.rect.left(), ti.rect.bottom()),
    //QPoint(ti.rect.right(), ti.rect.bottom()));
  } else {
    /*WidgetStatus imgType = isHover ? WidgetStatus::kHover : (ti.isFixed() ?
    WidgetStatus::kPressed : WidgetStatus::kNormal); SImage* imgLeft =
    ImgMgr::instance().image("guiframe_app_label_left", imgType,
    devicePixelRatioF()); SImage* imgMid =
    ImgMgr::instance().image("guiframe_app_label_mid", imgType,
    devicePixelRatioF()); SImage* imgRight =
    ImgMgr::instance().image("guiframe_app_label_right", imgType,
    devicePixelRatioF());

    if (imgLeft && imgMid && imgRight)
    {
            int leftWidth = imgLeft->rect().width() - imgGap;
            int rightWidth = imgRight->rect().width() - imgGap;

            QRect imgR = imgLeft->rect();
            imgR.adjust(imgGap, 0, 0, 0);

            QRect drawR(ti.rect);
            painter.drawImage(QRect(drawR.left(), drawR.top(), leftWidth,
    m_layout.tab_image_height), *imgLeft, imgR);

            painter.drawImage(QRect(drawR.left() + leftWidth, drawR.top(),
    drawR.width() - leftWidth - rightWidth, m_layout.tab_image_height),
    *imgMid);

            imgR = imgRight->rect();
            imgR.adjust(0, 0, -imgGap, 0);
            painter.drawImage(QRect(drawR.right() - rightWidth, drawR.top(),
    rightWidth, m_layout.tab_image_height), *imgRight, imgR);

    }
    else
    {

    }*/
    if (isHover) {
      painter.setBrush(QBrush(NAME_COLOR("TabBackHover")));
      painter.setPen(Qt::transparent);
      painter.drawRoundedRect(tabRect, 2, 2);
    } else {
      painter.setBrush(QBrush(NAME_COLOR("TabBackNormal")));
      painter.setPen(Qt::transparent);
      painter.drawRoundedRect(tabRect, 2, 2);
    }
  }

  // draw title
  QColor txtColor = NAME_COLOR("TextNormal");
  if (isActive) txtColor = NAME_COLOR("ContactBlack");
  // else if(ti.isFixed())
  //	txtColor = NAME_COLOR("Highlight");
  painter.setPen(txtColor);
  QRect txtDrawRect = tabRect /*.adjusted(6 *
                                 getAppInstance()->uiScale(),m_layout.image_top_gap,-6
                                 * getAppInstance()->uiScale(),0)*/
      ;
  int align = Qt::AlignCenter | Qt::AlignVCenter;
  if (txtDrawRect.width() <
      painter.fontMetrics().boundingRect(ti.title).width())
    align = Qt::AlignLeft | Qt::AlignVCenter;

  QFont font = painter.font();
  font.setPixelSize(12);
  font.setBold(true);
  painter.setFont(font);
  painter.drawText(txtDrawRect, align, ti.title);

  // draw close button
  if (!ti.isFixed() && isHover) {
    SImage* img =
        ImgMgr::instance().image(isActive ? "guiframe_app_label_close_select"
                                          : "guiframe_app_label_close",
                                 WidgetStatus::kNormal, devicePixelRatioF());
    if (img) {
      QRect r = tabRect /* ti.rect*/;
      QRect closeR(
          QPoint(
              r.right() - m_layout.clost_btn_gap - m_layout.close_btn_width,
              r.bottom() - m_layout.clost_btn_gap - m_layout.close_btn_width),
          QSize(m_layout.close_btn_width, m_layout.close_btn_width));
      painter.setRenderHint(QPainter::SmoothPixmapTransform);
      painter.drawImage(closeR, *img);
    }
  }

  if (isDraggingTab) painter.restore();
}

void TabBar::drawMoveBtns(QStylePainter& painter) {
  if (!m_layout.showMore) return;

  bool leftEnable = checkLeftHide();
  bool rightEnable = checkRightHide();

  SImage* img = ImgMgr::instance().image(
      "guiframe_app_label_move_left",
      leftEnable ? WidgetStatus::kNormal : WidgetStatus::kDisabled,
      devicePixelRatioF());
  painter.drawImage(m_rectMoveLeft, *img);

  img = ImgMgr::instance().image(
      "guiframe_app_label_move_right",
      rightEnable ? WidgetStatus::kNormal : WidgetStatus::kDisabled,
      devicePixelRatioF());
  painter.drawImage(m_rectMoveRight, *img);
}

int TabBar::hitTestTab(QPoint pos) {
  for (int i = 0; i < m_tabs.size(); ++i) {
    if (m_tabs[i].isHide()) continue;

    QRect r = m_tabs[i].rect.adjusted(0, m_layout.image_top_gap, 0, 0);
    if (r.contains(pos)) {
      return i;
    }
  }
  return -1;
}

int TabBar::tabPosById(int id) {
  for (int i = 0; i < m_tabs.size(); ++i) {
    if (m_tabs[i].winId == id) return i;
  }
  return -1;
}

void TabBar::startDrag() {
  QByteArray itemData;
  QDataStream dataStream(&itemData, QIODevice::WriteOnly);
  dataStream << m_dragTab.winId;
  QMimeData* mimeData = new QMimeData;
  mimeData->setData("application/x-dnditemdata", itemData);

  QDrag* drag = new QDrag(this);  // it will be deleteLater
  drag->setMimeData(mimeData);

  QPixmap pm = getDragPixmap();
  drag->setPixmap(pm);

  // bad code to process snapshot of qb window
  if (m_dragTab.isPopup()) {
    if (m_dragTab.widget->parent()) {
      dynamic_cast<QWidget*>(m_dragTab.widget->parent())->hide();
    } else
      m_dragTab.widget->hide();
  }

  m_dragging = true;

  drag->setDragCursor(m_pmDragCursor, Qt::DropAction::IgnoreAction);
  drag->setDragCursor(m_pmDragCursor, Qt::DropAction::MoveAction);
  Qt::DropAction da = drag->exec();
  m_dragging = false;

  if (da == Qt::IgnoreAction) {
    tabSeperated(m_dragTab);
  } else {
    tabActivated(m_dragTab.winId);
  }
}

void TabBar::doDragMove(int tabPosX) {
  int start = 1;  // 首页位置不变
  int end = m_fixedCount - 1;
  if (!m_dragTab.isFixed()) {
    start = m_fixedCount;
    end = m_tabs.size() - 1;
  }

  QRect r = m_dragTab.rect;
  r.setWidth(m_layout.active_tab_width);
  r.moveTo(QPoint(tabPosX, 0));

  int insertPos = -1;
  int tabPos = tabPosById(m_dragTab.winId);
  for (int i = start; i <= end; ++i) {
    const CmdWindowInfo& ti = m_tabs[i];
    if (ti.isHide() || ti.winId == m_dragTab.winId) continue;

    QRect insectRect = ti.rect.intersected(r);
    if (insectRect.isValid()) {
      if (tabPos == -1) {
        if (r.left() > ti.rect.center().x())
          insertPos = i + 1;
        else
          insertPos = i;
      } else if (insectRect.left() == ti.rect.left() &&
                 insectRect.right() - 5 > ti.rect.center().x())
        insertPos = i + 1;
      else if (insectRect.right() == ti.rect.right() &&
               insectRect.left() + 5 <= ti.rect.center().x())
        insertPos = i;
    }
    if (insertPos != -1)
      break;
    else if (i == m_tabs.size() - 1 && r.left() > ti.rect.right())
      insertPos = i + 1;
  }

  if (insertPos == -1 && !m_dragTab.isFixed() && m_tabs.size() == m_fixedCount)
    insertPos = m_fixedCount;

  if (insertPos > 0) {
    bool changed = false;
    if (tabPos == -1)  // 加入tab
    {
      insertTab(m_dragTab, insertPos);
      changed = true;
    } else if (insertPos != tabPos)  // 移动tab
    {
      if (tabPos < insertPos) --insertPos;
      m_tabs.move(tabPos, insertPos);
      changed = true;
    }
    if (changed) {
      stopAnimation();
      m_activePos = insertPos;
      layoutTabs();
      startAnimation();
    }
  }
  update();
}

void TabBar::onBtnClicked() {}

void TabBar::setProgress(int v) {
  bool needUpdate = false;
  if (v == 100)
    m_animating = false;
  else {
    float oldPercent = m_animateProgess / 100.0;
    m_animateProgess = v;
    float percent = v / 100.0;
    for (int i = 0; i < m_tabsForAnimate.size(); ++i) {
      QRect& r = m_tabsForAnimate[i].rect;
      QRect rDest = m_tabs[i].rect;

      int originX = (r.x() - oldPercent * rDest.x()) / (1 - oldPercent);
      int posDiff = originX + (rDest.x() - originX) * percent - r.x();

      int originWidth =
          (r.width() - oldPercent * rDest.width()) / (1 - oldPercent);
      int widthDiff =
          originWidth + (rDest.width() - originWidth) * percent - r.width();

      if (posDiff != 0 || widthDiff != 0) needUpdate = true;

      r.adjust(posDiff, 0, posDiff + widthDiff, 0);
    }
  }

  if (needUpdate || v == 100) repaint();
}

void TabBar::stopAnimation() {
  m_animation->stop();
  m_animateProgess = 0;
  m_animating = false;
}

void TabBar::startAnimation() {
  return;
  m_animateProgess = 0;
  m_animating = true;
  m_animation->start();
}

void TabBar::buildActions() {
  m_actionRefresh = new QAction(tr("刷新页面"), this);
  connect(m_actionRefresh, &QAction::triggered, this, &TabBar::onAction);

  m_actionFix = new QAction(tr("固定页面"), this);
  connect(m_actionFix, &QAction::triggered, this, &TabBar::onAction);

  m_actionClose = new QAction(tr("关闭页面"), this);
  connect(m_actionClose, &QAction::triggered, this, &TabBar::onAction);

  m_actionCloseOthers = new QAction(tr("关闭其他页面"), this);
  connect(m_actionCloseOthers, &QAction::triggered, this, &TabBar::onAction);

  m_actionCloseAll = new QAction(tr("关闭全部页面"), this);
  connect(m_actionCloseAll, &QAction::triggered, this, &TabBar::onAction);

  m_actionCloseAllBonds = new QAction(tr("关闭全部债券页面"), this);
  connect(m_actionCloseAllBonds, &QAction::triggered, this, &TabBar::onAction);

  connect(m_btnMore, &SImageButton::clicked, this, &TabBar::onAction);
  m_actionCloseAllBonds->setEnabled(false);

  m_actionUnfixAll = new QAction(tr("取消所有固定标签"), this);
  connect(m_actionUnfixAll, &QAction::triggered, this, &TabBar::onAction);

  m_actionFixedTabWidth = new QAction(tr("宽度固定(名称显示较完整)"), this);
  m_actionFixedTabWidth->setCheckable(true);
  connect(m_actionFixedTabWidth, &QAction::triggered, this, &TabBar::onAction);

  m_actionVariantTabWidth = new QAction(tr("宽度变形(标签显示数量较多)"), this);
  m_actionVariantTabWidth->setCheckable(true);
  connect(m_actionVariantTabWidth, &QAction::triggered, this,
          &TabBar::onAction);
}

void TabBar::showMoreMenu() {
  m_tabMenu = -1;
  /*
          菜单
          标签操作
                  关闭全部页面
                  关闭全部债券详情
                  取消所有固定标签
          标签显示偏好
                  宽度固定(名称显示较完整)
                  宽度变形(标签显示数量较多)
  */
  QMenu ctxMenu(this);
  // QWidgetAction
  QAction* label = ctxMenu.addAction(tr("标签操作"));
  label->setEnabled(false);
  ctxMenu.addAction(m_actionCloseAll);
  ctxMenu.addAction(m_actionCloseAllBonds);
  ctxMenu.addAction(m_actionUnfixAll);
  ctxMenu.addSeparator();
  label = ctxMenu.addAction(tr("标签显示偏好"));
  label->setEnabled(false);
  ctxMenu.addAction(m_actionFixedTabWidth);
  ctxMenu.addAction(m_actionVariantTabWidth);
  ctxMenu.setStyleSheet(
      QString("QMenu::item {padding:6px 38px 6px 18px;}\n"
              "QMenu::item:selected {color:#%1;}\n"
              "QMenu::item:hover {background-color:#%2;}\n"
              "QMenu::item:disabled {color:#%3;}\n"
              "QMenu {background-color:#%4; margin:0px;font:12px Microsoft "
              "YaHei;font-weight:bold;}\n"
              "QMenu::separator{height:1px; background:#%5; margin-left:10px; "
              "margin-right:10px;}")
          .arg(NAME_COLOR("Highlight").rgb(), 0, 16)
          .arg(NAME_COLOR("Hover").rgb(), 0, 16)
          .arg(NAME_COLOR("SupportingWord").rgb(), 0, 16)
          .arg(NAME_COLOR("ElementBackground").rgb(), 0, 16)
          //.arg(NAME_COLOR("TextNormal").rgb(), 0, 16)
          .arg(NAME_COLOR("PartPlate").rgb(), 0, 16));

  // 设置菜单状态
  m_actionCloseAll->setEnabled(m_tabs.size() > m_fixedCount);
  m_actionUnfixAll->setEnabled(m_fixedCount > 1);
  for (int i = m_fixedCount; i < m_tabs.size(); ++i) {
    if (m_tabs[i].cmdId == 20061) {
      m_actionCloseAllBonds->setEnabled(true);
      break;
    }
  }
  m_actionFixedTabWidth->setChecked(m_layout.fixedWidth);
  m_actionVariantTabWidth->setChecked(!m_layout.fixedWidth);
  // ctxMenu.exec(m_btnMore->mapToGlobal(m_btnMore->pos()));
  ctxMenu.exec(QCursor::pos());
}

void TabBar::unFixTab(int tabPos) {
  if (tabPos <= 0 || tabPos >= m_tabs.size()) return;
  if (m_tabs[tabPos].isFixed()) {
    m_tabs[tabPos].setFixed(false);
    if (m_tabs.size() > m_fixedCount && m_tabs[m_fixedCount].isHide()) {
      for (int i = m_fixedCount; i < m_tabs.size(); ++i) {
        m_tabs[i].setHide(false);
        m_hideTabs.removeOne(i);
      }
    }

    --m_fixedCount;
    m_tabs.move(tabPos, m_fixedCount);
  }
}

void TabBar::onAction() {
  if (sender() == m_actionFix) {
    if (m_tabs[m_tabMenu].isFixed()) {
      m_tabs[m_tabMenu].setFixed(false);
      if (m_tabs.size() > m_fixedCount && m_tabs[m_fixedCount].isHide()) {
        for (int i = m_fixedCount; i < m_tabs.size(); ++i) {
          m_tabs[i].setHide(false);
          m_hideTabs.removeOne(i);
        }
      }

      --m_fixedCount;
      m_tabs.move(m_tabMenu, m_fixedCount);

    } else {
      for (int& tab : m_hideTabs) {
        if (tab > m_tabMenu) --tab;
      }
      m_tabs[m_tabMenu].setFixed(true);
      m_tabs.move(m_tabMenu, m_fixedCount);
      ++m_fixedCount;
    }

  } else if (sender() == m_actionClose) {
    closeTab(m_tabMenu);
  } else if (sender() == m_actionCloseAll) {
    for (int i = m_tabs.size() - 1; i >= m_fixedCount; --i) {
      closeTab(i);
    }
  } else if (sender() == m_actionCloseOthers) {
    for (int i = m_tabs.size() - 1; i >= m_fixedCount; --i) {
      if (i == m_tabMenu) continue;
      closeTab(i);
    }
  } else if (sender() == m_actionCloseAllBonds) {
    for (int i = m_tabs.size() - 1; i >= m_fixedCount; --i) {
      if (m_tabs[i].cmdId != 20061) continue;
      closeTab(i);
    }
  } else if (sender() == m_actionUnfixAll) {
    while (m_fixedCount > 1) {
      unFixTab(m_fixedCount - 1);
    }
  } else if (sender() == m_actionFixedTabWidth) {
    m_layout.fixedWidth = true;
    m_layout.normal_tab_width = m_layout.active_tab_width;
  } else if (sender() == m_actionVariantTabWidth) {
    m_layout.fixedWidth = false;
  } else if (sender() == m_btnMore) {
    showMoreMenu();
  }

  if (sender() != m_actionRefresh)
    layoutTabs(sender() == m_actionFixedTabWidth ||
               sender() == m_actionVariantTabWidth);
}
